package logdbservice

import (
	"fmt"
	"strings"
	"time"
	"yunj/pkg/global"
	"yunj/pkg/yunj/app/dto"
	"yunj/pkg/yunj/app/model"
	"yunj/pkg/yunj/core/db"
	"yunj/pkg/yunj/core/redis"
	"yunj/pkg/yunj/util"
)

// 保存日志
func Save(param *dto.AdminMemberLogRecordParam) (err error) {
	// 加锁（等待）
	lock := redis.NewLock(fmt.Sprintf("admin.log.save:%d", param.Id), 10*time.Second, true)
	ok, lockErr := lock.Get()
	if lockErr != nil {
		err = fmt.Errorf("日志%d保存锁获取异常！%v", param.Id, lockErr)
		return
	}
	if !ok {
		err = fmt.Errorf("日志%d保存锁未获取到！", param.Id)
		return
	}
	defer lock.Release()

	// 获取要添加的数据
	tableSuffix, logData, logAttrData, err := getSaveData(param)
	// fmt.Printf("1111111|%v|%v\r\n", param.Desc, logAttrData)
	if err != nil {
		err = fmt.Errorf("获取要保存的数据异常！%v", err)
		return
	}
	if logData == nil && logAttrData == nil {
		return
	}
	// 数据处理
	// log
	logDB := db.Model(&model.AdminMemberLog{}).SetTableNameSuffix(tableSuffix)
	var logExistsCount int64
	if err = logDB.GormDB().Where("id = ?", param.Id).Count(&logExistsCount).Error; err != nil {
		err = fmt.Errorf("查询日志%d数据是否存在异常！%v", param.Id, err)
		return
	}
	if logExistsCount > 0 {
		if err = logDB.Change(*logData).Error; err != nil {
			err = fmt.Errorf("修改日志%d数据异常！%v", param.Id, err)
			return
		}
	} else {
		// fmt.Printf("11111111|%v\r\n", *logData)
		if err = logDB.Add(*logData).Error; err != nil {
			err = fmt.Errorf("添加日志%d数据异常！%v", param.Id, err)
			return
		}
	}
	// log_attr
	if logAttrData != nil {
		logAttrDB := db.Model(&model.AdminMemberLogAttr{}).SetTableNameSuffix(tableSuffix)
		var logAttrExistsCount int64
		if err = logAttrDB.GormDB().Where("log_id = ?", param.Id).Count(&logAttrExistsCount).Error; err != nil {
			err = fmt.Errorf("查询日志%d属性数据是否存在异常！%v", param.Id, err)
			return
		}
		if logAttrExistsCount > 0 {
			if err = logAttrDB.Change(*logAttrData).Error; err != nil {
				err = fmt.Errorf("修改日志%d属性数据异常！%v", param.Id, err)
				return
			}
		} else {
			if err = logAttrDB.Add(*logAttrData).Error; err != nil {
				err = fmt.Errorf("添加日志%d属性数据异常！%v", param.Id, err)
				return
			}
		}
	}

	// fmt.Printf("123123|%v\r\n", *param)
	return
}

// 获取保存数据
func getSaveData(param *dto.AdminMemberLogRecordParam) (tableSuffix string, logData *map[string]any, logAttrData *map[string]any, err error) {
	// 数据表后缀
	createdAt, err := time.ParseInLocation("2006-01-02 15:04:05", param.CreatedAt, time.Local)
	if err != nil {
		err = fmt.Errorf("时间%s解析出错:%v", param.CreatedAt, err)
		return
	}
	tableSuffix = "_" + createdAt.Format("200601")
	// 日志数据
	logData, err = getSaveLogData(param, &createdAt)
	if err != nil {
		return
	}
	// 日志属性数据
	logAttrData, err = getSaveLogAttrData(param)
	if err != nil {
		return
	}
	return
}

// 获取要保存的日志属性数据
func getSaveLogAttrData(param *dto.AdminMemberLogRecordParam) (logAttrData *map[string]any, err error) {
	logAttr := &model.AdminMemberLogAttr{
		LogId: param.Id,
	}
	if param.UserAgent != "" {
		logAttr.UserAgent = param.UserAgent
	}
	if param.RequestParams != "" {
		logAttr.RequestParams = param.RequestParams
	}
	if param.ResponseContent != "" {
		logAttr.ResponseContent = param.ResponseContent
	}
	if param.Desc != "" {
		logAttr.Desc = param.Desc
	}
	logAttrDataRaw := util.StructToMap(logAttr)
	if len(logAttrDataRaw) <= 1 {
		// 判断只有1个字段时，不处理
		return
	}
	logAttrData = &logAttrDataRaw
	return
}

// 获取要保存的日志数据
func getSaveLogData(param *dto.AdminMemberLogRecordParam, createdAt *time.Time) (logData *map[string]any, err error) {
	log := &model.AdminMemberLog{
		Id:        param.Id,
		CreatedAt: createdAt,
	}
	if param.AuthKey != "" {
		log.AuthKey = param.AuthKey
	}
	if param.Url != "" {
		log.Url = param.Url
	}
	if param.Method != "" {
		log.Method = param.Method
	}
	if param.MemberId > 0 {
		log.MemberId = param.MemberId
	}
	if param.DataId != "" {
		log.DataId = param.DataId
	}
	if log.DataId == "" {
		log.DataId = getDefaultDataIdByRequestParams(param.RequestParams)
	}
	if param.Ip != "" {
		log.Ip = param.Ip
		var ipRegion string
		ipRegion, err = util.IpRegion(param.Ip)
		if err != nil {
			err = fmt.Errorf("获取ip区域信息失败！%v", err)
			return
		}
		if ipRegion != "" {
			log.IpRegion = ipRegion
			log.IpProvince = util.IpRegionProvince(ipRegion)
		}
	}
	if param.UserAgent != "" {
		// 解析User-Agent
		uaClient := global.Uaparser.Parse(param.UserAgent)
		if uaClient != nil {
			// 系统平台
			if uaClient.Os.Family != "" {
				log.Platform = uaClient.Os.Family
			}
			// 系统平台版本号
			if uaClient.Os.Major != "" {
				log.PlatformVersion = uaClient.Os.Major
				if uaClient.Os.Minor != "" {
					log.PlatformVersion += "." + uaClient.Os.Minor
				}
			}
			// 浏览器
			if uaClient.UserAgent.Family != "" {
				log.Browser = uaClient.UserAgent.Family
			}
			// 浏览器版本号
			if uaClient.UserAgent.Major != "" {
				log.BrowserVersion = uaClient.UserAgent.Major
				if uaClient.UserAgent.Minor != "" {
					log.BrowserVersion += "." + uaClient.UserAgent.Minor
				}
			}
		}
	}
	if param.Latency > 0 {
		log.Latency = param.Latency
	}
	logDataRaw := util.StructToMap(log)
	if len(logDataRaw) <= 2 {
		// 判断只有2个字段时，不处理
		return
	}
	logData = &logDataRaw
	return
}

// 从JSON字符串中提取可能的id字段
func getDefaultDataIdByRequestParams(requestParams string) (dataId string) {
	if requestParams == "" {
		return
	}
	data, err := util.JsonTo[map[string]any](requestParams)
	if err != nil {
		return
	}
	// 先判断是否有id字段
	includeIdValue := "" // 待包含的id字段值
	for k, v := range data {
		if v == "" || v == nil {
			continue
		}
		kLower := strings.ToLower(k)
		if kLower == "id" && util.IsComparable(v) {
			if vStr, err := util.ToString(v); err == nil {
				dataId = vStr
				return
			}
		}
		if kLower == "pks" {
			if pksValue, err := util.ToAnySlice(v); err == nil && len(pksValue) > 0 {
				if pksValue0, err := util.ToString(pksValue[0]); err == nil {
					dataId = pksValue0
					return
				}
			}
		}
		if (strings.HasSuffix(kLower, "_id") || strings.HasSuffix(kLower, "id")) && util.IsComparable(v) {
			if vStr, err := util.ToString(v); err == nil {
				includeIdValue = vStr
			}
		}
	}
	dataId = includeIdValue
	return
}
